//package com.sunlands.deskmate.sales.sender.http;
//
//import com.alibaba.fastjson.JSON;
//import com.sunlands.deskmate.entity.MsgEntity;
//import com.sunlands.deskmate.sales.business.ClientInfoManager;
//import com.sunlands.deskmate.sales.business.sale.SalesClient;
//import com.sunlands.deskmate.sales.business.sale.SalesInfo;
//import com.sunlands.deskmate.sales.channel.ChannelManager;
//import com.sunlands.deskmate.sales.message.ResourcePackageMessage;
//import com.sunlands.deskmate.sales.sender.AbstractMessageSender;
//import com.sunlands.deskmate.sales.sender.dispatch.DispatchEvent;
//import com.sunlands.deskmate.sales.sender.dispatch.DispatchEventEnum;
//import com.sunlands.deskmate.sales.sender.dispatch.SendDispatcher;
//import com.sunlands.deskmate.sales.sender.dispatch.UnsyncMessageAcquire;
//import com.sunlands.deskmate.sales.storager.unsync.UnsyncMessageStorager;
//import com.sunlands.deskmate.sales.util.SpringUtils;
//import lombok.AllArgsConstructor;
//import lombok.Data;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.data.util.Pair;
//import org.springframework.http.HttpEntity;
//import org.springframework.http.HttpMethod;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.ResponseEntity;
//import org.springframework.http.client.ClientHttpResponse;
//import org.springframework.util.LinkedMultiValueMap;
//import org.springframework.util.MultiValueMap;
//import org.springframework.util.StopWatch;
//import org.springframework.web.client.DefaultResponseErrorHandler;
//import org.springframework.web.client.RestTemplate;
//import org.springframework.web.util.UriComponentsBuilder;
//
//import java.net.URI;
//import java.util.*;
//
///**
// * @author liude
// * @author anjunling@sunlands.com
// */
//@Slf4j
//public abstract class AbstractHttpMessageSender extends AbstractMessageSender {
//    public static final int maxTimeInMillis = 1000;
//    protected ChannelInfo channelInfo;
//    protected String url;
//    protected List<MsgEntity> messages;
//    protected boolean sendResult;
//
//    protected UnsyncMessageStorager unsyncMessageStorager;
//
//    protected UnsyncMessageAcquire unsyncMessageAcquire;
//
//    protected ClientInfoManager clientInfoManager;
//
//    protected AbstractHttpMessageSender() {
//        unsyncMessageStorager = SpringUtils.getBean("unsyncMessageStorager", UnsyncMessageStorager.class);
//        unsyncMessageAcquire = SpringUtils.getBean("unsyncMessageAcquire", UnsyncMessageAcquire.class);
//        clientInfoManager = SpringUtils.getBean(ClientInfoManager.class);
//    }
//
//    protected abstract Integer strategy();
//
//
//    public void send() {
//        if (messages == null || messages.isEmpty()) {
//            log.warn("messages is empty");
//            release();
//            return;
//        }
//        try {
//            Integer strategy = strategy();
//            List<MsgEntity> result = null;
//            ResponseEntity response = null;
//            Pair<Optional<MsgEntity>, List<MsgEntity>> pair = splitByResourcePackageMessage(messages);
//            do {
//
//                //发送消息
//                if (!pair.getFirst().isPresent()) {
//                    result = pair.getSecond();
//                    response = sendMessage(result);
//                } else if (pair.getSecond().isEmpty()) {
//                    result = Arrays.asList(pair.getFirst().get());
//                    response = sendResourcePackageMessages(pair.getFirst().get());
//                }
//
//                if (response.getStatusCode().value() != HttpStatus.OK.value()) {
//                    sendResult = false;
//                } else {
//                    sendResult = true;
//                }
//            } while (!sendResult && strategy != null && strategy-- > 0);
//
//            if (sendResult) {
//                MsgEntity outboundMessage = result.get(result.size() - 1);
//                //同步成功
//                String clientIdentityUserKey = channelInfo.getSessionKey();
//
//                List<MsgEntity> unreadMessage = unsyncMessageAcquire.getUnreadMessage(clientIdentityUserKey, 0L, outboundMessage.getAckId());
//                unsyncMessageStorager.setLatestReadMessageId(clientIdentityUserKey, outboundMessage.getAckId());
//
//                epochNext();
//                //MQ 历史消息和用户信息更新
//                success(unreadMessage);
//            }
//            log.info("send sendResult = {} response = {}  size = {} strategy = {} channelInfo = {} messages = {} ", sendResult, response, messages.size(), strategy, channelInfo, JSON.toJSONString(messages));
//        } catch (Exception e) {
//            log.error(String.format("send fail channelInfo %s messages %s ", channelInfo, JSON.toJSONString(messages)), e);
//        }
//    }
//
//    /**
//     * 将消息列表按顺序拆分成资源包和非资源包多个段，进行分段发送
//     * 下边是拆分的例子: (M1表示第1个非资源消息, R2表示第2个资源消息, 以此类推)
//     * <p>
//     * example1: R1, R2, M1, M2, M3, M4  => (R1),(R2),(M1, M2, M3, M4)
//     * example2: M1, M2, R1, R2, M3, M4  => (M1, M2), (R1, R2),(M3, M4)
//     * example3: M1, M2, M3, M4, R1, R2  => (M1, M2, M3, M4),(R1)(R2)
//     *
//     * @param messages 消息列表
//     * @return Pair, First为前序的资源包, Second为后序的非资源包
//     */
//    private Pair<Optional<MsgEntity>, List<MsgEntity>> splitByResourcePackageMessage(List<MsgEntity> messages) {
//        Optional<MsgEntity> resourcePackageMessages = Optional.empty();
//        List<MsgEntity> nonResourcePackageMessages = new ArrayList<>();
//
//        for (MsgEntity message : messages) {
//            if (message.getContent() instanceof ResourcePackageMessage) {
//                if (nonResourcePackageMessages.isEmpty()) {
//                    resourcePackageMessages = Optional.of(message);
//                }
//                break;
//            } else {
//                nonResourcePackageMessages.add(message);
//            }
//        }
//        return Pair.of(resourcePackageMessages, nonResourcePackageMessages);
//    }
//
//    private ResponseEntity<String> sendResourcePackageMessages(MsgEntity resourcePackageMessages) {
//        Map<String, String> headers = new HashMap<>();
//        headers.put("Content-Type", "application/json;charset=utf-8");
//
//        this.url = clientInfoManager.clientInfo("mp", "user").getResourcePackageCallbackUrl();
//        ResourceCardDTO resourceCard = convert(resourcePackageMessages);
//
//        Map<String, String> param = new HashMap<>();
//        param.put("openId", resourceCard.openId);
//        param.put("staffUserName", resourceCard.staffUserName);
//        param.put("resourceCardId", resourceCard.resourceCardId);
//        param.put("appId", resourceCard.appId);
//        return post(url, param, headers, null);
//
//    }
//
//    private ResponseEntity<String> sendMessage(List<MsgEntity> messages) {
//        Map<String, String> headers = new HashMap<>();
//        headers.put("Content-Type", "application/json;charset=utf-8");
//        String body = JSON.toJSONString(messages);
//        this.url = clientInfoManager.clientInfo("mp", "user").getCallbackUrl();
//        StopWatch stopWatch = new StopWatch();
//        stopWatch.start("post message to mp client");
//        ResponseEntity<String> result = post(url, null, headers, body);
//        stopWatch.stop();
//        if (stopWatch.getTotalTimeMillis() > maxTimeInMillis) {
//            log.error("发送消息耗时 {} 毫秒 body {}", stopWatch.getTotalTimeMillis(), body);
//        }
//        return result;
//    }
//
//
//    private ResponseEntity<String> post(String baseUrl, Map<String, String> queryParams, Map<String, String> headers, String body) {
//        MultiValueMap<String, String> queryMaps = new LinkedMultiValueMap<>();
//        if (Objects.nonNull(queryParams)) {
//            queryParams.forEach((key, value) -> queryMaps.put(key, Collections.singletonList(value)));
//        }
//
//        URI uri = UriComponentsBuilder.fromHttpUrl(baseUrl).queryParams(queryMaps).build().toUri();
//
//        MultiValueMap<String, String> headerMaps = new LinkedMultiValueMap<>();
//        if (Objects.nonNull(headers)) {
//            headers.forEach((key, value) -> headerMaps.put(key, Collections.singletonList(value)));
//        }
//
//        HttpEntity<String> entity = new HttpEntity<>(body, headerMaps);
//
//        RestTemplate restTemplate = new RestTemplate();
//        restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
//            @Override
//            public void handleError(ClientHttpResponse response) {
//            }
//        });
//        log.debug("post请求参数： url = {} entity = {}", uri, entity.toString());
//        ResponseEntity<String> responseEntity = restTemplate.exchange(uri, HttpMethod.POST, entity, String.class);
//        log.info("post请求结果responseEntity = {}", responseEntity.toString());
//        return responseEntity;
//    }
//
//    private ResourceCardDTO convert(MsgEntity message) {
//
//        SalesClient client = SpringUtils.getBean(SalesClient.class);
//        try {
//            SalesInfo salesInfo = client.getSalesUser(Integer.parseInt(message.getFromId()));
//            salesInfo.getUsername();
//            return new ResourceCardDTO(message.getToId(), salesInfo.getUsername(), ((ResourcePackageMessage) message.getContent()).getResourceCardId(), ((ResourcePackageMessage) message.getContent()).getAppId());
//        } catch (Exception e) {
//            log.error("convert sales {} salesId, error {}", message.getFromId(), e.getMessage());
//        }
//        return null;
//    }
//
//    /**
//     * http发送方式，结束后，释放锁，并通知进行下一轮发送，知道消息为空
//     */
//    protected void epochNext() {
//        //解锁
//        SendDispatcher sendDispatcher = SpringUtils.getBean(SendDispatcher.class);
//        DispatchEvent dispatchEvent = new DispatchEvent(DispatchEventEnum.UNSYNC, channelInfo);
//        sendDispatcher.epochNext(dispatchEvent);
//        log.debug("http release channelInfo {}", channelInfo);
//    }
//
//    protected void release() {
//        //解锁
//        SendDispatcher sendDispatcher = SpringUtils.getBean(SendDispatcher.class);
//        DispatchEvent dispatchEvent = new DispatchEvent(DispatchEventEnum.UNSYNC, channelInfo);
//        sendDispatcher.unlockEpoch(dispatchEvent);
//
//        log.debug("http release channelInfo {}", channelInfo);
//    }
//
//    @Data
//    @AllArgsConstructor
//    public static class ResourceCardDTO {
//        private String openId;
//        private String staffUserName;
//        private String resourceCardId;
//        private String appId;
//    }
//}
